home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / GLUT-3.7 / PROGS / advanced97 / LIGHTMAP.C < prev    next >
Encoding:
C/C++ Source or Header  |  1998-08-12  |  24.7 KB  |  1,053 lines

  1. #include <GL/glut.h>
  2. #include <math.h>
  3. #include <stdio.h>
  4. #include "texture.h"
  5. #include <stdlib.h>
  6.  
  7. #ifndef __sgi
  8. /* Most math.h's do not define float versions of the math functions. */
  9. #define sqrtf(x) (float)sqrt((x))
  10. #endif
  11.  
  12. #if !defined(GL_VERSION_1_1) && !defined(GL_VERSION_1_2)
  13. #define glBindTexture glBindTextureEXT
  14. #endif
  15.  
  16. #define CHECK_ERROR(str)                                           \
  17. {                                                                  \
  18.     GLenum error;                                                  \
  19.     if(error = glGetError())                                       \
  20.        printf("GL Error: %s (%s)\n", gluErrorString(error), str);  \
  21. }
  22.  
  23. /* display lists */
  24. enum {SPHERE = 1, CONE, LIGHT, DISK, FLOOR, BACK, LEFT, RIGHT, CEIL};
  25.  
  26. /* texture objects */
  27. enum {DEFAULT, LIGHTMAP, SURFMAP}; 
  28.  
  29. enum {NONE, LIGHT_XY, LIGHT_Z, LIGHT_INTENS};
  30.  
  31. #ifndef TRUE
  32. enum {FALSE, TRUE};
  33. #endif
  34. enum {X, Y, Z, W};
  35. enum {R, G, B, A};
  36.  
  37. GLfloat staticlightpos[] = {50.f, 70.f, -10.f, 1.f};
  38. GLfloat lightpos[] = {50.f, 70.f, -10.f, 1.f};
  39. GLfloat intensity = 1.f;
  40. GLfloat nearScale = .49f, farScale = .0001f;
  41.  
  42. int dblbuf = TRUE;
  43. int action = NONE;
  44. int winWidth = 512;
  45. int winHeight = 512;
  46. int curtess = 1; /* current tessellation level */
  47. int lasttess = 1; /* last set tessellation level */
  48.  
  49. void
  50. reshape(int wid, int ht)
  51. {
  52.     winWidth = wid;
  53.     winHeight = ht;
  54.     glViewport(0, 0, wid, ht);
  55. }
  56.  
  57. void
  58. motion(int x, int y)
  59. {
  60.     switch(action)
  61.     {
  62.     case LIGHT_XY:
  63.     lightpos[X] = (x - winWidth/2) * 200.f/winWidth;
  64.     lightpos[Y] = (winHeight/2 - y) * 200.f/winHeight;
  65.     glutPostRedisplay();
  66.     break;
  67.     case LIGHT_Z:
  68.     lightpos[Z] = (winHeight/2 - y) * 200.f/winWidth;
  69.     glutPostRedisplay();
  70.     break;
  71.     case LIGHT_INTENS:
  72.     intensity = x/(GLfloat)winWidth;
  73.     glutPostRedisplay();
  74.     break;
  75.     }
  76. }
  77.  
  78. void
  79. mouse(int button, int state, int x, int y)
  80. {
  81.     if(state == GLUT_DOWN)
  82.     switch(button)
  83.     {
  84.     case GLUT_LEFT_BUTTON: /* move the light */
  85.         action = LIGHT_XY;
  86.         motion(x, y);
  87.         break;
  88.     case GLUT_MIDDLE_BUTTON:
  89.         action = LIGHT_INTENS;
  90.         motion(x, y);
  91.         break;
  92.     case GLUT_RIGHT_BUTTON: /* move the polygon */
  93.         action = LIGHT_Z;
  94.         motion(x, y);
  95.         break;
  96.     }
  97. }
  98.  
  99.  
  100. /*
  101. ** Create a single component texture map
  102. */
  103. GLfloat *make_texture(int maxs, int maxt)
  104. {
  105.     int s, t;
  106.     GLfloat *texture;
  107.  
  108.     texture = (GLfloat *)malloc(maxs * maxt * sizeof(GLfloat));
  109.     for(t = 0; t < maxt; t++) {
  110.     for(s = 0; s < maxs; s++) {
  111.         texture[s + maxs * t] = ((s >> 3) & 0x1) ^ ((t >> 3) & 0x1);
  112.     }
  113.     }
  114.     return texture;
  115. }
  116.  
  117. /* make tesselated surface for display list dlist */
  118. /* normal tells you surface position and orientation */
  119. /* count = tesselation count */
  120. void
  121. tess_surface(GLuint dlist, int count)
  122. {
  123.     int i, j;
  124.     GLfloat x0, y0, z0;
  125.     GLfloat over[3], up[3]; /* axes */
  126.     int Sindex, Tindex; /* active texture axes */
  127.  
  128.     glNewList(dlist, GL_COMPILE);
  129.     glBegin(GL_QUADS);
  130.  
  131.     switch(dlist)
  132.     {
  133.     case FLOOR:
  134.     glNormal3f( 0.f,  1.f, 0.f);
  135.     x0 = -100.f; y0 = -100.f; z0 = 100.f;
  136.     over[X] = 1.f/count; over[Y] = 0.f; over[Z] = 0.f;
  137.     up[X] = 0.f; up[Y] = 0.f; up[Z] = -1.f/count;
  138.     Sindex = X; Tindex = Z;
  139.     break;
  140.     case CEIL:
  141.     glNormal3f( 0.f, -1.f, 0.f);
  142.     x0 = -100.f; y0 = 100.f; z0 = 100.f;
  143.     over[X] = 0.f; over[Y] = 0.f; over[Z] = -1.f/count;
  144.     up[X] = 1.f/count; up[Y] = 0.f; up[Z] = 0.f;
  145.     Sindex = X; Tindex = Z;
  146.     break;
  147.     case LEFT:
  148.     glNormal3f( 1.f,  0.f, 0.f);
  149.     x0 = -100.f; y0 = -100.f; z0 = 100.f;
  150.     over[X] = 0.f; over[Y] = 0.f; over[Z] = -1.f/count; 
  151.     up[X] = 0.f; up[Y] = 1.f/count; up[Z] = 0.f;
  152.     Sindex = Z; Tindex = Y;
  153.     break;
  154.     case RIGHT:
  155.     glNormal3f(-1.f,  0.f, 0.f);
  156.     x0 =  100.f; y0 = -100.f; z0 = 100.f;
  157.     over[X] = 0.f; over[Y] = 1.f/count; over[Z] = 0.f;
  158.     up[X] = 0.f; up[Y] = 0.f; up[Z] = -1.f/count; 
  159.     Sindex = Z; Tindex = Y;
  160.     break;
  161.     case BACK:
  162.     glNormal3f( 0.f,  0.f, 1.f);
  163.     x0 = -100.f; y0 = -100.f; z0 = -100.f;
  164.     over[X] = 1.f/count; over[Y] = 0.f; over[Z] = 0.f;
  165.     up[X] = 0.f; up[Y] = 1.f/count; up[Z] = 0.f;
  166.     Sindex = X; Tindex = Y;
  167.     break;
  168.     default:
  169.     fprintf(stderr, "tess_surface(): bad display list argument %d\n",
  170.         dlist);
  171.     glEnd();
  172.     glEndList();
  173.     return;
  174.     }
  175.  
  176.     for(j = 0; j < count; j++)
  177.     for(i = 0; i < count; i++)
  178.     {
  179.         glTexCoord2f(i * over[Sindex], j * up[Tindex]);
  180.         glVertex3f(x0 + i * 200 * over[X] + j * 200 * up[X],
  181.                y0 + i * 200 * over[Y] + j * 200 * up[Y],
  182.                z0 + i * 200 * over[Z] + j * 200 * up[Z]);
  183.         glTexCoord2f((i + 1) * over[Sindex], j * up[Tindex]);
  184.         glVertex3f(x0 + (i + 1) * 200 * over[X] + j * 200 * up[X],
  185.                y0 + (i + 1) * 200 * over[Y] + j * 200 * up[Y],
  186.                z0 + (i + 1) * 200 * over[Z] + j * 200 * up[Z]);
  187.         glTexCoord2f((i + 1) * over[Sindex], (j + 1) * up[Tindex]);
  188.         glVertex3f(x0 + (i + 1) * 200 * over[X] + (j + 1) * 200 * up[X],
  189.                y0 + (i + 1) * 200 * over[Y] + (j + 1) * 200 * up[Y],
  190.                z0 + (i + 1) * 200 * over[Z] + (j + 1) * 200 * up[Z]);
  191.         glTexCoord2f(i * over[Sindex], (j + 1) * up[Tindex]);
  192.         glVertex3f(x0 + i * 200 * over[X] + (j + 1) * 200 * up[X],
  193.                y0 + i * 200 * over[Y] + (j + 1) * 200 * up[Y],
  194.                z0 + i * 200 * over[Z] + (j + 1) * 200 * up[Z]);
  195.     }
  196.     glEnd();
  197.     glEndList();
  198. }
  199.  
  200.  
  201.  
  202.  
  203.  
  204. static GLfloat zero[] = {0.f, 0.f, 0.f, 1.f};
  205. static GLfloat one[] = {1.f, 1.f, 1.f, 1.f};
  206. static GLfloat diff[] = {.25f, .25f, .25f, .25f};
  207.  
  208.  
  209. /* create a lightmap simulating a local light with attenuation */
  210. void
  211. make_lightmap(GLenum light, int dim)
  212. {
  213.     GLfloat quadratic, linear, constant;
  214.     GLfloat diffuse[4], ambient[4]; /* light color */
  215.     GLfloat *texture;
  216.     GLfloat dist, scale, edge;
  217.     int size;
  218.     int i, j;
  219.  
  220.     glPushAttrib(GL_TEXTURE_BIT);
  221.     /* get from light to simplify api */
  222.     glGetLightfv(light, GL_QUADRATIC_ATTENUATION, &quadratic);
  223.     glGetLightfv(light, GL_LINEAR_ATTENUATION, &linear);
  224.     glGetLightfv(light, GL_CONSTANT_ATTENUATION, &constant);
  225.  
  226.     glGetLightfv(light, GL_AMBIENT, ambient);
  227.     glGetLightfv(light, GL_DIFFUSE, diffuse);
  228.  
  229.     size = dim + 2;
  230.     texture = (GLfloat *)malloc(sizeof(GLfloat) * 3 * size * size);
  231.  
  232.     dist = dim/2; /* 1 in from border */
  233.     edge = 1.f/(constant + linear * dist + quadratic * dist * dist);
  234.  
  235.     for(j = 0; j < size; j++)
  236.     for(i = 0; i < size; i++)
  237.     {
  238.         dist = sqrtf((float)((size/2.f - i) * (size/2.f - i) +
  239.                  (size/2.f - j) * (size/2.f - j)));
  240.         scale = 1.f/(constant + linear * dist + quadratic * dist * dist);
  241.         if(dist >= dim/2)
  242.         {
  243.         texture[3 * (i + size * j) + 0] = 
  244.             diffuse[R] * edge + ambient[R];
  245.         texture[3 * (i + size * j) + 1] = 
  246.             diffuse[G] * edge + ambient[G];
  247.         texture[3 * (i + size * j) + 2] = 
  248.             diffuse[B] * edge + ambient[B];
  249.         }
  250.         else
  251.         {
  252.         texture[3 * (i + size * j) + 0] = 
  253.             diffuse[R] * scale + ambient[R];
  254.         texture[3 * (i + size * j) + 1] = 
  255.             diffuse[G] * scale + ambient[G];
  256.         texture[3 * (i + size * j) + 2] = 
  257.             diffuse[B] * scale + ambient[B];
  258.         }
  259.     }
  260.  
  261.     glBindTexture(GL_TEXTURE_2D, LIGHTMAP);
  262.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  263.  
  264.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  265.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
  266.  
  267.     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 
  268.          size, size, 1, GL_RGB, GL_FLOAT, texture);
  269.     free(texture);
  270.     glPopAttrib();
  271. }
  272.  
  273. /* draw a highly tesselated disk with local light */
  274. void
  275. draw_lightmap(int dim, int dist)
  276. {
  277.     GLUquadricObj *qobj;
  278.     GLfloat *texture;
  279.     GLfloat light[4] = {0.f, 0.f, 1.f, 1.f};
  280.  
  281.     texture = (GLfloat *)malloc(sizeof(GLfloat) * 3 * dim * dim);
  282.  
  283.     glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  284.  
  285.     glPushMatrix(); /* starts as modelview */
  286.     glLoadIdentity();
  287.     glTranslatef(0.f, 0.f, -dist);
  288.  
  289.     glMatrixMode(GL_PROJECTION);
  290.     glPushMatrix();
  291.     glLoadIdentity();
  292.     glOrtho(-dim/2., dim/2., -dim/2., dim/2., 0., (double)dist);
  293.  
  294.     glPushAttrib(GL_LIGHTING_BIT|GL_VIEWPORT_BIT);
  295.     glViewport(0, 0, dim, dim);
  296.     glEnable(GL_LIGHTING);
  297.  
  298.     light[Z] = dist;
  299.     glLightfv(GL_LIGHT0, GL_POSITION, light); /* light position */
  300.  
  301.     /* XXX TODO, range check an report errors */
  302.     glDisable(GL_TEXTURE_2D);
  303.  
  304.     qobj = gluNewQuadric();
  305.     gluDisk(qobj, 0., dim/2. * sqrt(2.), dim/4, dim/4);
  306.     gluDeleteQuadric(qobj);
  307.  
  308.     glEnable(GL_TEXTURE_2D);
  309.     glPopAttrib();
  310.     glPopMatrix();
  311.     glMatrixMode(GL_MODELVIEW);
  312.     glPopMatrix();
  313.  
  314.     glReadPixels(0, 0, dim, dim, GL_RGB, GL_FLOAT, texture);
  315.  
  316.     glBindTexture(GL_TEXTURE_2D, LIGHTMAP);
  317.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  318.     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, dim, dim, 0, GL_RGB,
  319.          GL_FLOAT, texture);
  320.  
  321.     free(texture);
  322. }
  323.  
  324.  
  325. int texdim = 256;
  326.  
  327.  
  328. /* draw the lightmap texture */
  329. void redraw_lightmap(void)
  330. {
  331.     glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  332.  
  333.     glPushAttrib(GL_LIGHTING_BIT|GL_TEXTURE_BIT);
  334.  
  335.     /* assume GL_MODELVIEW */
  336.     glPushMatrix();
  337.     glLoadIdentity();
  338.     glMatrixMode(GL_PROJECTION);
  339.     glPushMatrix();
  340.     glLoadIdentity();
  341.  
  342.     glEnable(GL_TEXTURE_2D);
  343.     glBindTexture(GL_TEXTURE_2D, LIGHTMAP);
  344.     glDisable(GL_LIGHTING);
  345.  
  346.     glColor3f(1.f, 1.f, 1.f);
  347.     glBegin(GL_QUADS);
  348.     glTexCoord2i(0, 0);
  349.     glVertex2i(-1, -1);
  350.  
  351.     glTexCoord2i(1, 0);
  352.     glVertex2i(1, -1);
  353.  
  354.     glTexCoord2i(1, 1);
  355.     glVertex2i(1,  1);
  356.  
  357.     glTexCoord2i(0, 1);
  358.     glVertex2i(-1,  1);
  359.     glEnd();
  360.  
  361.     glPopMatrix();
  362.     glMatrixMode(GL_MODELVIEW);
  363.     glPopMatrix();
  364.  
  365.     glPopAttrib();
  366.  
  367.     CHECK_ERROR("OpenGL Error in redraw_map()");
  368.  
  369.     if(dblbuf)
  370.     glutSwapBuffers(); 
  371.     else
  372.     glFlush(); 
  373. }
  374.  
  375. /* draw the lightmap texture */
  376. void redraw_combomap(void)
  377. {
  378.     GLfloat scale;
  379.     glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  380.  
  381.     glPushAttrib(GL_LIGHTING_BIT|GL_TEXTURE_BIT|GL_COLOR_BUFFER_BIT|
  382.          GL_DEPTH_BUFFER_BIT);
  383.  
  384.     /* assume GL_MODELVIEW */
  385.     glPushMatrix();
  386.     glLoadIdentity();
  387.     glMatrixMode(GL_PROJECTION);
  388.     glPushMatrix();
  389.     glLoadIdentity();
  390.  
  391.     glEnable(GL_TEXTURE_2D);
  392.     glDisable(GL_LIGHTING);
  393.  
  394.  
  395.     glBindTexture(GL_TEXTURE_2D, SURFMAP);
  396.  
  397.     glColor3f(intensity, intensity, intensity);
  398.     glBegin(GL_QUADS);
  399.     glTexCoord2i(0, 0);
  400.     glVertex2i(-1, -1);
  401.  
  402.     glTexCoord2i(5, 0);
  403.     glVertex2i(1, -1);
  404.  
  405.     glTexCoord2i(5, 5);
  406.     glVertex2i(1,  1);
  407.  
  408.     glTexCoord2i(0, 5);
  409.     glVertex2i(-1,  1);
  410.     glEnd();
  411.  
  412.     glEnable(GL_BLEND);
  413.     glDepthFunc(GL_LEQUAL);
  414.     glBlendFunc(GL_ZERO, GL_SRC_COLOR);
  415.     glBindTexture(GL_TEXTURE_2D, LIGHTMAP);
  416.  
  417.     glMatrixMode(GL_TEXTURE);
  418.     glPushMatrix();
  419.     glTranslatef(.5f, .5f, 0.f);
  420.     scale = .25f + (lightpos[Z] + 100.f) * 3.75f/200.f;
  421.     glScalef(scale, scale, 0.f);
  422.     glTranslatef(-.5f, -.5f, 0.f);
  423.     glTranslatef(-lightpos[X]/200.f, -lightpos[Y]/200.f, 0.f);
  424.  
  425.     glColor3f(1.f, 1.f, 1.f);
  426.     glBegin(GL_QUADS);
  427.     glTexCoord2i(0, 0);
  428.     glVertex2i(-1, -1);
  429.  
  430.     glTexCoord2i(1, 0);
  431.     glVertex2i(1, -1);
  432.  
  433.     glTexCoord2i(1, 1);
  434.     glVertex2i(1,  1);
  435.  
  436.     glTexCoord2i(0, 1);
  437.     glVertex2i(-1,  1);
  438.     glEnd();
  439.  
  440.     /* GL_TEXTURE */
  441.     glPopMatrix();
  442.     glMatrixMode(GL_PROJECTION);
  443.     glPopMatrix();
  444.     glMatrixMode(GL_MODELVIEW);
  445.     glPopMatrix();
  446.  
  447.     glPopAttrib();
  448.  
  449.     CHECK_ERROR("OpenGL Error in redraw_combomap()");
  450.  
  451.     if(dblbuf)
  452.     glutSwapBuffers(); 
  453.     else
  454.     glFlush(); 
  455. }
  456.  
  457. /* draw the openGL scene with lighting off */
  458. void render_scene(int tess)
  459. {
  460.     /* material properties for objects in scene */
  461.  
  462.     /* update tessellation if it changed */
  463.     if(tess != lasttess)
  464.     {
  465.     tess_surface(FLOOR, tess);
  466.     tess_surface(CEIL,  tess);
  467.     tess_surface(LEFT,  tess);
  468.     tess_surface(RIGHT, tess);
  469.     tess_surface(BACK,  tess);
  470.     lasttess = tess;
  471.     }
  472.     glPushAttrib(GL_LIGHTING_BIT|GL_TEXTURE_BIT);
  473.  
  474.     /* floor */
  475.     glColor3f(.5f, .35f, .35f); /* reddish */
  476.     glEnable(GL_TEXTURE_2D);
  477.     glCallList(FLOOR);
  478.     glDisable(GL_TEXTURE_2D);
  479.  
  480.     /* ceiling */
  481.     glColor3f(.35f, .5f, .35f); /* greenish */
  482.     glCallList(CEIL);
  483.  
  484.     /* right wall */
  485.     glColor3f(.35f, .35f, .5f); /* bluish */
  486.     glCallList(RIGHT);
  487.  
  488.     /* left wall */
  489.     glCallList(LEFT);
  490.  
  491.     /* back wall */
  492.     glCallList(BACK);
  493.  
  494.     /* draw the sphere */
  495.     
  496.     glCallList(SPHERE);
  497.  
  498.     /* draw the cone */
  499.     glCallList(CONE);
  500.  
  501.     /* draw the light */
  502.     glPushMatrix();
  503.     glTranslatef(lightpos[X], lightpos[Y], lightpos[Z]);
  504.     glCallList(LIGHT);
  505.     glPopMatrix();
  506.  
  507.     glPopAttrib();
  508.     CHECK_ERROR("OpenGL Error in render_unlit()");
  509. }
  510.  
  511. void
  512. redraw_opengl(void)
  513. {
  514.     glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  515.     glPushAttrib(GL_LIGHTING_BIT);
  516.  
  517.     glEnable(GL_LIGHTING);
  518.     glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
  519.     glEnable(GL_COLOR_MATERIAL);
  520.     glLightfv(GL_LIGHT0, GL_POSITION, lightpos); /* opengl lit */ 
  521.  
  522.  
  523.     render_scene(curtess);
  524.  
  525.     glPopAttrib();
  526.  
  527.     if(dblbuf)
  528.     glutSwapBuffers(); 
  529.     else
  530.     glFlush(); 
  531. }
  532.  
  533.  
  534. void
  535. redraw_unlit(void)
  536. {
  537.     glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  538.     glPushAttrib(GL_LIGHTING_BIT);
  539.  
  540.     glDisable(GL_LIGHTING);
  541.     render_scene(1);
  542.  
  543.     glPopAttrib();
  544.  
  545.     if(dblbuf)
  546.     glutSwapBuffers(); 
  547.     else
  548.     glFlush(); 
  549. }
  550.  
  551.  
  552. /* draw the scene white, modulated by lightmap */
  553. /* unlit, uncolored simulated by lighting */
  554. /* texgen overrides texture coords */
  555. void render_white(void)
  556. {
  557.     GLfloat scale;
  558.  
  559.     /* texgen used to override texure coords */
  560.     static GLfloat XZs[] = {1/200.f, 0.f, 0.f, .5f};
  561.     static GLfloat XZt[] = {0.f, 0.f, 1/200.f, .5f};
  562.  
  563.     static GLfloat YZs[]  = {0.f, 0.f, 1/200.f, .5f};
  564.     static GLfloat YZt[]  = {0.f, 1/200.f, 0.f, .5f};
  565.  
  566.     static GLfloat XYs[]  = {1/200.f, 0.f, 0.f, .5f};
  567.     static GLfloat XYt[]  = {0.f, 1/200.f, 0.f, .5f};
  568.  
  569.     /* material properties for objects in scene */
  570.  
  571.     glPushAttrib(GL_LIGHTING_BIT|GL_TEXTURE_BIT);
  572.  
  573.     glTexGenf(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
  574.     glTexGenf(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
  575.  
  576.     glEnable(GL_LIGHTING);
  577.  
  578.     /* simulate unlit, color = white */
  579.     glLightfv(GL_LIGHT0, GL_AMBIENT, diff);
  580.     glMaterialfv(GL_FRONT, GL_DIFFUSE, zero);
  581.     glColorMaterial(GL_FRONT, GL_AMBIENT);
  582.     glEnable(GL_COLOR_MATERIAL);
  583.  
  584.     glEnable(GL_TEXTURE_2D);
  585.     glBindTexture(GL_TEXTURE_2D, LIGHTMAP);
  586.     
  587.     glEnable(GL_TEXTURE_GEN_S);
  588.     glEnable(GL_TEXTURE_GEN_T);
  589.     glMatrixMode(GL_TEXTURE);
  590.     glPushMatrix();
  591.  
  592.     glTexGenfv(GL_S, GL_OBJECT_PLANE, XZs);
  593.     glTexGenfv(GL_T, GL_OBJECT_PLANE, XZt);
  594.  
  595.     glLoadIdentity();
  596.     glTranslatef(.5f, .5f, 0.f);
  597.     scale = nearScale - (nearScale - farScale)/200.f * (100.f + lightpos[Y]);
  598.     glScalef(scale, scale, 1.f);
  599.     glTranslatef(-.5f, -.5f, 0.f);
  600.     glTranslatef(-lightpos[X]/200.f, -lightpos[Z]/200.f, 0.f);
  601.     /* add intensity (colorchange) */
  602.  
  603.     scale = lightpos[Y] + 100;
  604.     scale /= 200.f;
  605.     scale *= scale;
  606.     scale = 1.f/(1.f + scale);
  607.     scale = 1.f;
  608.     glColor3f(scale, scale, scale);
  609.  
  610.     /* floor */
  611.     glCallList(FLOOR);
  612.  
  613.     glLoadIdentity();
  614.     glTranslatef(.5f, .5f, 0.f);
  615.     scale = nearScale - (nearScale - farScale)/200.f * (100.f - lightpos[Y]);
  616.     glScalef(scale, scale, 1.f);
  617.     glTranslatef(-.5f, -.5f, 0.f);
  618.     glTranslatef(-lightpos[X]/200.f, -lightpos[Z]/200.f, 0.f);
  619.  
  620.     scale = 100 - lightpos[Y];
  621.     scale /= 100.f;
  622.     scale *= scale;
  623.     scale = 1.f/(1.f + scale);
  624.     scale = 1.f;
  625.     glColor3f(scale, scale, scale);
  626.  
  627.     /* ceiling */
  628.      glCallList(CEIL);
  629.  
  630.     glTexGenfv(GL_S, GL_OBJECT_PLANE, YZs);
  631.     glTexGenfv(GL_T, GL_OBJECT_PLANE, YZt);
  632.     glLoadIdentity();
  633.     glTranslatef(.5f, .5f, 0.f);
  634.     scale = nearScale - (nearScale - farScale)/200.f * (100.f - lightpos[X]);
  635.     glScalef(scale, scale, 1.f);
  636.     glTranslatef(-.5f, -.5f, 0.f);
  637.     glTranslatef(-lightpos[Z]/200.f, -lightpos[Y]/200.f, 0.f);
  638.  
  639.     scale = 100 - lightpos[X];
  640.     scale /= 100.f;
  641.     scale *= scale;
  642.     scale = 1.f/(1.f + scale);
  643.     scale = 1.f;
  644.     glColor3f(scale, scale, scale);
  645.  
  646.     /* right wall */
  647.     glCallList(RIGHT);
  648.  
  649.     glLoadIdentity();
  650.     glTranslatef(.5f, .5f, 0.f);
  651.     scale = nearScale - (nearScale - farScale)/200.f * (100.f + lightpos[X]);
  652.     glScalef(scale, scale, 1.f);
  653.     glTranslatef(-.5f, -.5f, 0.f);
  654.     glTranslatef(-lightpos[Z]/200.f, -lightpos[Y]/200.f, 0.f);
  655.  
  656.     scale = lightpos[X] + 100;
  657.     scale /= 100.f;
  658.     scale *= scale;
  659.     scale = 1.f/(1.f + scale);
  660.     scale = 1.f;
  661.     glColor3f(scale, scale, scale);
  662.  
  663.     /* left wall */
  664.     glCallList(LEFT);
  665.  
  666.     glTexGenfv(GL_S, GL_OBJECT_PLANE, XYs);
  667.     glTexGenfv(GL_T, GL_OBJECT_PLANE, XYt);
  668.     glLoadIdentity();
  669.     glTranslatef(.5f, .5f, 0.f);
  670.     scale = nearScale - (nearScale - farScale)/200.f * (100.f + lightpos[Z]);
  671.     glScalef(scale, scale, 1.f);
  672.     glTranslatef(-.5f, -.5f, 0.f);
  673.     glTranslatef(-lightpos[X]/200.f, -lightpos[Y]/200.f, 0.f);
  674.  
  675.     scale = lightpos[Z] + 100;
  676.     scale /= 100.f;
  677.     scale *= scale;
  678.     scale = 1.f/(1.f + scale);
  679.     scale = 1.f;
  680.     glColor3f(scale, scale, scale);
  681.  
  682.     /* back wall */
  683.     glCallList(BACK);
  684.  
  685.     /* done with texture matrix */
  686.     glPopMatrix();
  687.     glMatrixMode(GL_MODELVIEW);
  688.  
  689.     /* no contribution to highly tesselated objects */
  690.     glMaterialfv(GL_FRONT, GL_AMBIENT, zero);
  691.     glLightfv(GL_LIGHT0, GL_AMBIENT, zero);
  692.  
  693.     /* draw the sphere */
  694.     
  695.     glCallList(SPHERE);
  696.  
  697.     /* draw the cone */
  698.     glCallList(CONE);
  699.  
  700.     glPopAttrib();
  701.     CHECK_ERROR("OpenGL Error in render_white()");
  702. }
  703.  
  704. void
  705. redraw_white(void)
  706. {
  707.     glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  708.     render_white();
  709.  
  710.     if(dblbuf)
  711.     glutSwapBuffers(); 
  712.     else
  713.     glFlush(); 
  714. }
  715.  
  716.  
  717. void
  718. redraw_lightmapped(void)
  719. {
  720.     glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  721.  
  722.     glPushAttrib(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_LIGHTING_BIT);
  723.     glDisable(GL_LIGHTING);
  724.     render_scene(1);
  725.     glEnable(GL_LIGHTING);
  726.     glEnable(GL_BLEND);
  727.     glBlendFunc(GL_ZERO, GL_SRC_COLOR);
  728.     glDepthFunc(GL_LEQUAL);
  729.     render_white();
  730.     glPopAttrib();
  731.  
  732.     if(dblbuf)
  733.     glutSwapBuffers(); 
  734.     else
  735.     glFlush(); 
  736. }
  737.  
  738. void
  739. redraw_maponly(void)
  740. {
  741.     glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  742.  
  743.     glPushAttrib(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_LIGHTING_BIT);
  744.     glDisable(GL_LIGHTING);
  745.     render_scene(1);
  746.     glEnable(GL_LIGHTING);
  747.     glEnable(GL_BLEND);
  748.     glBlendFunc(GL_ZERO, GL_SRC_COLOR);
  749.     glDepthFunc(GL_LEQUAL);
  750.     render_white();
  751.     glBlendFunc(GL_ONE, GL_ONE);
  752.     glDisable(GL_LIGHTING); /* add in unlit scene again */
  753.     render_scene(1);
  754.     
  755.     glPopAttrib();
  756.  
  757.     if(dblbuf)
  758.     glutSwapBuffers(); 
  759.     else
  760.     glFlush(); 
  761. }
  762.  
  763. void
  764. redraw_complete(void)
  765. {
  766.     glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  767.  
  768.     glPushAttrib(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_LIGHTING_BIT);
  769.  
  770.     glLightfv(GL_LIGHT0, GL_POSITION, lightpos); /* opengl lit */ 
  771.     glDisable(GL_LIGHTING);
  772.     render_scene(1);
  773.     glEnable(GL_LIGHTING);
  774.     glEnable(GL_BLEND);
  775.     glBlendFunc(GL_ZERO, GL_SRC_COLOR);
  776.     glDepthFunc(GL_LEQUAL);
  777.     render_white();
  778.     glBlendFunc(GL_ONE, GL_ONE);
  779.     glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
  780.     glEnable(GL_COLOR_MATERIAL);
  781.     render_scene(1);
  782.  
  783.     glPopAttrib();
  784.  
  785.     if(dblbuf)
  786.     glutSwapBuffers(); 
  787.     else
  788.     glFlush(); 
  789. }
  790.  
  791.  
  792.  
  793. /* ARGSUSED1 */
  794. void key(unsigned char key, int x, int y)
  795. {
  796.     switch(key)
  797.     {
  798.     case 'l': /* show lightmap */
  799.     glutDisplayFunc(redraw_lightmap);
  800.     glutPostRedisplay();
  801.     break;
  802.     case 'w': /* show white scene modulated by lightmap */
  803.     glutDisplayFunc(redraw_white);
  804.     glutPostRedisplay();
  805.     break;
  806.     case 'm': /* unlit scene modified by lightmap */
  807.     glutDisplayFunc(redraw_lightmapped);
  808.     glutPostRedisplay();
  809.     break;
  810.     case 'u': /* draw scene without lighting */
  811.     glutDisplayFunc(redraw_unlit);
  812.     glutPostRedisplay();
  813.     break;
  814.     case 'o': /* draw scene lit using OpenGL */
  815.     glutDisplayFunc(redraw_opengl);
  816.     glutPostRedisplay();
  817.     break;
  818.     case 'a': /* show scene lit with OpenGL and lightmaps */
  819.     glutDisplayFunc(redraw_complete);
  820.     glutPostRedisplay();
  821.     break;
  822.     case 'p': /* show scene lit with pure lightmaps */
  823.     glutDisplayFunc(redraw_maponly);
  824.     glutPostRedisplay();
  825.     break;
  826.     case 'x': /* surface texture with lightmap combined */
  827.     glutDisplayFunc(redraw_combomap);
  828.     glutPostRedisplay();
  829.     break;
  830.     case 'T': /* surface texture with lightmap combined */
  831.     curtess++;
  832.     glutPostRedisplay();
  833.     break;
  834.     case 't': /* surface texture with lightmap combined */
  835.     curtess--;
  836.     if(curtess < 1)
  837.         curtess = 1;
  838.     glutPostRedisplay();
  839.     break;
  840.     case '1': /* surface texture with lightmap combined */
  841.     curtess = 1;
  842.     glutPostRedisplay();
  843.     break;
  844.     case 'y':
  845.     farScale -= .0001f;
  846.     if(farScale < .0001f)
  847.         farScale = .0001f;
  848.     printf("farScale = %.4f\n", farScale);
  849.     glutPostRedisplay();
  850.     break;
  851.     case 'Y':
  852.     farScale += .0001f;
  853.     printf("farScale = %.4f\n", farScale);
  854.     glutPostRedisplay();
  855.     break;
  856.     case 'z':
  857.     nearScale -= .01f;
  858.     if(nearScale < .01f)
  859.         nearScale = .01f;
  860.     printf("nearScale = %.2f\n", nearScale);
  861.     glutPostRedisplay();
  862.     break;
  863.     case 'Z':
  864.     nearScale += .01f;
  865.     printf("nearScale = %.2f\n", nearScale);
  866.     glutPostRedisplay();
  867.     break;
  868.     case '\033':
  869.     exit(0);
  870.     break;
  871.     case '?':
  872.     case 'h':
  873.     default:
  874.     fprintf(stderr, 
  875.         "Keyboard Commands\n"
  876.         "l - draw lightmap\n"
  877.         "w - draw white scene modulated by lightmap\n"
  878.         "m - draw unlit scene modified by lightmap\n"
  879.         "u - draw unlit scene\n"
  880.         "o - draw scene lit by OpenGL\n"
  881.         "a - draw scene lit by OpenGL (tess = 1) + lightmaps\n"
  882.         "p - draw scene lit only by lightmaps\n"
  883.         "x - interactive lightmap on brick wall\n"
  884.         "T - increase surface tessellation\n"
  885.         "t - decrease surface tessellation\n"
  886.         "1 - set tessellation to one\n"
  887.         "y - decrease far scale for lightmaps\n"
  888.         "Y - increase far scale for lightmaps\n"
  889.         "z - decrease near scale for lightmaps\n"
  890.         "Z - increase near scale for lightmaps\n");
  891.     break;
  892.     }
  893.     glutPostRedisplay();
  894. }
  895.  
  896.  
  897.  
  898.  
  899. main(int argc, char *argv[])
  900. {
  901.     GLfloat *tex;
  902.  
  903.     GLUquadricObj *qobj;
  904.  
  905.     glutInit(&argc, argv);
  906.     glutInitWindowSize(winWidth, winHeight);
  907.     if(argc > 1)
  908.     {
  909.     char *args = argv[1];
  910.     int done = FALSE;
  911.     while(!done)
  912.     {
  913.         switch(*args)
  914.         {
  915.         case 's': /* single buffer */
  916.         printf("Single Buffered\n");
  917.         dblbuf = FALSE;
  918.         break;
  919.         case '-': /* do nothing */
  920.         break;
  921.         case 0:
  922.         done = TRUE;
  923.         break;
  924.         }
  925.         args++;
  926.     }
  927.     }
  928.  
  929.     if(dblbuf)
  930.     glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE);
  931.     else
  932.     glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH);
  933.  
  934.  
  935.     (void)glutCreateWindow("example program");
  936.     glutDisplayFunc(redraw_opengl);
  937.     glutKeyboardFunc(key);
  938.     glutMouseFunc(mouse);
  939.     glutMotionFunc(motion);
  940.     glutReshapeFunc(reshape);
  941.  
  942.     /* draw a perspective scene */
  943.     glMatrixMode(GL_PROJECTION);
  944.     glFrustum(-100., 100., -100., 100., 300., 501.); 
  945.     glMatrixMode(GL_MODELVIEW);
  946.     /* look at scene from (0, 0, 400) */
  947.     gluLookAt(0., 0., 400., 0., 0., 0., 0., 1., 0.);
  948.  
  949.     /* turn on features */
  950.     glEnable(GL_DEPTH_TEST);
  951.     glEnable(GL_LIGHT0);
  952.     glLightfv(GL_LIGHT0, GL_POSITION, staticlightpos);
  953.  
  954.     /* remove back faces to speed things up */
  955.     glCullFace(GL_BACK);
  956.  
  957.  
  958.     /* make a display list containing a sphere */
  959.     glNewList(SPHERE, GL_COMPILE);
  960.     {
  961.     glPushMatrix();
  962.     glTranslatef(0.f, -80.f, -80.f);
  963.     qobj = gluNewQuadric();
  964.     gluQuadricTexture(qobj, GL_TRUE);
  965.     glColor3f(.5f, .25f, 0.f);
  966.     gluSphere(qobj, 20.f, 20, 20);
  967.     gluDeleteQuadric(qobj);
  968.     glPopMatrix();
  969.     }
  970.     glEndList();
  971.  
  972.     /* make a display list containing a sphere */
  973.     glNewList(LIGHT, GL_COMPILE);
  974.     {
  975.     qobj = gluNewQuadric();
  976.     glColor3f(1.f, 1.f, 1.f);
  977.     glPushAttrib(GL_LIGHTING_BIT);
  978.     glDisable(GL_LIGHTING);
  979.     gluSphere(qobj, 3.f, 20, 20);
  980.     glPopAttrib();
  981.     gluDeleteQuadric(qobj);
  982.     }
  983.     glEndList();
  984.  
  985.     /* create a display list containing a cone */
  986.     glNewList(CONE, GL_COMPILE);
  987.     {
  988.     glPushMatrix();
  989.     glTranslatef(-60.f, -100.f, -5.f);
  990.  
  991.     qobj = gluNewQuadric();
  992.     gluQuadricTexture(qobj, GL_TRUE);
  993.     glRotatef(-90.f, 1.f, 0.f, 0.f);
  994.     glColor3f(0.f, .25f, .5f);
  995.  
  996.     gluCylinder(qobj, 20., 0., 60., 20, 20);
  997.     gluDeleteQuadric(qobj);
  998.  
  999.     qobj = gluNewQuadric();
  1000.     gluQuadricOrientation(qobj, GLU_INSIDE);
  1001.     gluDisk(qobj, 0., 20., 20, 1);
  1002.     gluDeleteQuadric(qobj);
  1003.     glPopMatrix();
  1004.     }
  1005.     glEndList();
  1006.  
  1007.     /* load pattern for current 2d texture */
  1008.     tex = make_texture(128, 128);
  1009.  
  1010.     /* makes texturing faster, and looks better than GL_LINEAR */
  1011.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  1012.     glTexImage2D(GL_TEXTURE_2D, 0, 1, 128, 128, 0, GL_RED, GL_FLOAT, tex);
  1013.     free(tex);
  1014.  
  1015.     {
  1016.     GLuint *surftex;
  1017.     int texwid, texht, texcomps;
  1018.     surftex = read_texture("data/brick.rgb", &texwid, &texht, &texcomps);
  1019.  
  1020.     glBindTexture(GL_TEXTURE_2D, SURFMAP);
  1021.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  1022.  
  1023.     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texwid, texht, 0, GL_RGBA,
  1024.              GL_UNSIGNED_BYTE, surftex);
  1025.  
  1026.     }
  1027.  
  1028.     glBindTexture(GL_TEXTURE_2D, DEFAULT);
  1029.  
  1030.     tess_surface(FLOOR, 1);
  1031.     tess_surface(CEIL, 1);
  1032.     tess_surface(LEFT, 1);
  1033.     tess_surface(RIGHT, 1);
  1034.     tess_surface(BACK, 1);
  1035.  
  1036.     /* 1/80 intensity at edges */
  1037.     glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, 100.f/(texdim * texdim/4));
  1038.     /* 1/2 intensity at edges */
  1039.     glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, 1.f/texdim/2);
  1040.     glLightfv(GL_LIGHT1, GL_DIFFUSE, one);
  1041.  
  1042.     make_lightmap(GL_LIGHT1, 128);
  1043.  
  1044.     key('?', 0, 0);
  1045.  
  1046.     CHECK_ERROR("end of main");
  1047.  
  1048.     glutMainLoop();
  1049.  
  1050.     return 0;
  1051. }
  1052.  
  1053.